/*
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.android.apps.mytracks.services.sensors.ant;

import com.dsi.ant.AntMesg;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Sensor.SensorData;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Sensor.SensorState;

import android.content.SharedPreferences;
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;

/**
 * Tests {@link AntDirectSensorManager}
 *
 * @author Sandor Dornbush
 * @author Matthew Simmons
 */
public class AntDirectSensorManagerTest extends AndroidTestCase {
  private static class TestAntSensorHandler implements AntSensorHandler {
    public static final SensorDataSet sensorDataSet = SensorDataSet.newBuilder()
        .setCreationTime(0x12345678)
        .setHeartRate(SensorData.newBuilder()
            .setState(SensorState.SENDING)
            .setValue(0xfeed))
        .build();


    private short deviceNumber = (short) 0x1234;

    @Override
    public AntSensor getSensorType() {
      return AntSensor.SENSOR_HEART_RATE;
    }

    @Override
    public byte getChannelNumber() {
      return (byte) 4;
    }

    @Override
    public short getDeviceNumber() {
      return deviceNumber;
    }

    @Override
    public void setDeviceNumber(short deviceNumber) {
      this.deviceNumber = deviceNumber;
    }

    @Override
    public SensorDataSet handleBroadcastData(byte[] antMessage) {
      return sensorDataSet;
    }
  };

  private SharedPreferences sharedPreferences;
  private AntSensorHandler handler;
  private AntDirectSensorManager manager;

  public void setUp() {
    sharedPreferences = getContext().getSharedPreferences(
        Constants.SETTINGS_NAME, 0);
    // Let's use default values.
    sharedPreferences.edit().clear().commit();
    handler = new TestAntSensorHandler();
    manager = new AntDirectSensorManager(getContext(), handler);
  }

  public void testBroadcastData_reachesSensorHandler() throws Exception {
    byte[] message = new byte[9];
    message[0] = handler.getChannelNumber();
    manager.handleMessage(AntMesg.MESG_BROADCAST_DATA_ID, message);

    SensorDataSet dataSet = manager.getSensorDataSet();
    assertNotNull(dataSet);

    MoreAsserts.assertEquals(TestAntSensorHandler.sensorDataSet.toByteArray(),
        TestAntSensorHandler.sensorDataSet.toByteArray());
  }

  public void testBroadcastData_ignoredIfUnknownChannel() throws Exception {
    byte[] message = new byte[9];
    message[0] = (byte) (handler.getChannelNumber() ^ 0xff);
    manager.handleMessage(AntMesg.MESG_BROADCAST_DATA_ID, message);

    assertNull(manager.getSensorDataSet());
  }

  @SmallTest
  public void testSetDeviceNumber() throws Exception {
    handler.setDeviceNumber((short) 1);

    byte[] message = new byte[9];
    message[0] = handler.getChannelNumber();
    message[1] = 42;
    manager.handleMessage(AntMesg.MESG_CHANNEL_ID_ID, message);

    assertEquals(42, handler.getDeviceNumber());
  }

  @SmallTest
  public void testResponseEvent() throws Exception {
    assertEquals(Sensor.SensorState.NONE, manager.getSensorState());

    byte[] message = new byte[3];
    message[0] = handler.getChannelNumber();  // channel
    message[1] = AntMesg.MESG_UNASSIGN_CHANNEL_ID;
    message[2] = 0;  // code
    manager.handleMessage(AntMesg.MESG_RESPONSE_EVENT_ID, message);

    assertEquals(Sensor.SensorState.DISCONNECTED, manager.getSensorState());
    assertNull(manager.getSensorDataSet());
  }

  // TODO: Test timeout too.
}
